home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-07-16 | 18.5 KB | 717 lines | [TEXT/CWIE] |
- // ===========================================================================
- // CGraphPane.cp ©1995-97 Timo Eloranta All rights reserved.
- // ===========================================================================
- // This class displays the best drawing on the screen.
-
- #include "CGraphPane.h"
- #include "CGraphGAApp.h"
- #include "MyUtils.h"
- #include "GraphGA_PaneIDs.h"
-
- #include <UDrawingState.h>
- #include <UGWorld.h>
- #include <UModalDialogs.h>
- #include <LGAEditField.h>
- #include <LWindow.h>
- #include <LClipboard.h>
- #include <LString.h>
- #include <UDesktop.h>
-
- Int16 kMaxSquareSizes[70+1] =
-
- { 0, 0, 173, 113, 85, 67, 57, 49, 42, 38, 33,
- 31, 29, 26, 24, 23, 21, 20, 19, 18, 17,
- 16, 15, 15, 14, 14, 13, 12, 12, 12, 11,
- 11, 11, 10, 10, 10, 9, 9, 9, 8, 8,
- 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
- 6, 6, 6, 6, 6, 6, 6, 6, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
-
- Int16 kSquareSizes[ ] =
-
- { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 23, 24, 26, 29, 31, 33, 38, 42, 49, 57, 67, 85, 113, 173 };
-
- const RGBColor blackRGB = { 0, 0, 0 };
- const RGBColor l_greyRGB = { 0xEEEE, 0xEEEE, 0xEEEE }; // light grey
- const RGBColor d_greyRGB = { 0x8000, 0x8000, 0x8000 }; // 50% grey
- const RGBColor D_greyRGB = { 0x2000, 0x2000, 0x2000 }; // 87,5% grey
- const RGBColor goldenRGB = { 0xFFFF, 0x9C9C, 0x0808 };
-
-
- #define _72dpi 0x00480000
-
- // ---------------------------------------------------------------------------
- // • CGraphPane
- //
- // Called by: URegistrar::CreateObject
- // ---------------------------------------------------------------------------
-
- CGraphPane::CGraphPane(
- LStream *inStream)
- : LView(inStream)
- {
- CalcLocalFrameRect( mFrameRect );
- mGWorld = new LGWorld( mFrameRect, 0 );
-
- if (! mGWorld )
- ::StopAlert( ALRT_Offscreen, nil);
-
- mGraph = nil;
-
- mFullWindow = true;
- mShowGrid = true;
- mShowEdges = true;
- mShowNodes = true;
- mDarkGrid = true;
- mUseColor = true;
-
- mGridSquareSize = max_Int16;
-
- ToggleMenuItem( cmd_ShowGrid, str_HideGrid);
- ToggleMenuItem( cmd_ShowEdges, str_HideEdges);
- ToggleMenuItem( cmd_ShowNodes, str_HideNodes);
- ToggleMenuItem( cmd_BrightenGrid, str_BrightenGrid);
- ToggleMenuItem( cmd_BlackAndWhite, str_ToBlackAndWhite);
-
- ((LWindow *) mSuperView) -> GetStandardSize( mWindStdSize);
- }
-
- // ---------------------------------------------------------------------------
- // • ~CGraphPane
- // ---------------------------------------------------------------------------
- // Destructor
-
- CGraphPane::~CGraphPane()
- {
- if ( mGWorld )
- delete mGWorld;
- }
-
- // ---------------------------------------------------------------------------
- // • ObeyCommand
- //
- // Called by: LCommander::ProcessCommand
- // ---------------------------------------------------------------------------
- // Respond to commands
-
- Boolean
- CGraphPane::ObeyCommand(
- CommandT inCommand,
- void *ioParam)
- {
- Boolean cmdHandled = true,
- bRefreshNeeded = false;
-
- switch (inCommand) {
-
- case cmd_Copy:
- PlaceInClipboard(); // Place picture of the drawing to clipboard
- break;
-
- case cmd_ShowDrawing:
- mFullWindow = (mFullWindow) ? false : true;
- ((LWindow *) mSuperView) -> SendAESetZoom();
- if (mFullWindow)
- bRefreshNeeded = true;
- break;
-
- case cmd_ShowGrid:
- mShowGrid = (mShowGrid) ? false : true;
- bRefreshNeeded = true;
- if (mShowGrid)
- ToggleMenuItem( cmd_ShowGrid, str_HideGrid);
- else ToggleMenuItem( cmd_ShowGrid, str_ShowGrid);
- break;
-
- case cmd_ShowEdges:
- mShowEdges = (mShowEdges) ? false : true;
- bRefreshNeeded = true;
- if (mShowEdges)
- ToggleMenuItem( cmd_ShowEdges, str_HideEdges);
- else ToggleMenuItem( cmd_ShowEdges, str_ShowEdges);
- break;
-
- case cmd_ShowNodes:
- mShowNodes = (mShowNodes) ? false : true;
- bRefreshNeeded = true;
- if (mShowNodes)
- ToggleMenuItem( cmd_ShowNodes, str_HideNodes);
- else ToggleMenuItem( cmd_ShowNodes, str_ShowNodes);
- break;
-
- case cmd_BrightenGrid:
- mDarkGrid = (mDarkGrid) ? false : true;
- bRefreshNeeded = true;
- if (mDarkGrid)
- ToggleMenuItem( cmd_BrightenGrid, str_BrightenGrid);
- else ToggleMenuItem( cmd_BrightenGrid, str_DarkenGrid);
- break;
-
- case cmd_BlackAndWhite:
- mUseColor = (mUseColor) ? false : true;
- if (mUseColor)
- ToggleMenuItem( cmd_BlackAndWhite, str_ToBlackAndWhite);
- else ToggleMenuItem( cmd_BlackAndWhite, str_SwitchToColor);
-
- InvalidateDrawing( false );
- LPane::Draw( nil );
- break;
-
- case cmd_IncreaseSquareSize:
- case cmd_DecreaseSquareSize:
- mGridSquareSize =
- GetNextSquareSize( inCommand == cmd_IncreaseSquareSize );
- mNodeSize = SelectNodeSize();
- CalculateGridRect();
-
- InvalidateDrawing( false );
- LPane::Draw( nil );
- break;
-
- case cmd_SetSquareSize:
- Int32 theSize = mGridSquareSize;
-
- if ( UModalDialogs::AskForOneNumber(
- this, WIND_SetSize, edit_SquareSize, theSize )) {
- // Entry confirmed, set new value
-
- if ( ValidSquareSize( theSize ) ) {
- mGridSquareSize = theSize;
- mNodeSize = SelectNodeSize();
- CalculateGridRect();
-
- InvalidateDrawing( false );
- LPane::Draw( nil );
- } else {
- LStr255 theParam0( theSize );
- LStr255 theParam1( (Int32) mApp -> GetGridSize() );
- LStr255 theParam2( 5L );
- LStr255 theParam3( (Int32) mMaxSquareSize );
- UDesktop::Deactivate();
- ::ParamText( theParam0, theParam1, theParam2, theParam3);
- ::StopAlert( ALRT_InvalidSquareSize, nil );
- UDesktop::Activate();
- }
- }
- break;
-
-
- default:
- cmdHandled = LCommander::ObeyCommand(inCommand, ioParam);
- break;
- }
-
- if (bRefreshNeeded)
- InvalidateDrawing( true );
-
- return cmdHandled;
- }
-
- // ---------------------------------------------------------------------------
- // • FindCommandStatus
- //
- // Called by: LCommander::ProcessCommandStatus
- // ---------------------------------------------------------------------------
- // Determine which menu items will be enabled when we're on duty in the chain
- // of command.
-
- void
- CGraphPane::FindCommandStatus(
- CommandT inCommand,
- Boolean &outEnabled,
- Boolean &outUsesMark,
- Char16 &outMark,
- Str255 outName)
- {
- SDimension16 theCurWindSize;
-
- // Determine whether we currently show the drawing by
- // comparing the current size of the window to the so called
- // standard size, which in our case equals the min size.
- // If the current size is bigger than the std size, the
- // drawing pane is visible/shown/used ...
-
- ((LWindow *) mSuperView) -> GetFrameSize( theCurWindSize );
- mFullWindow = ( theCurWindSize.width > mWindStdSize.width );
-
- outUsesMark = false; // None of our commands use mark
-
- switch (inCommand) {
-
- case cmd_ShowDrawing:
- if (mFullWindow)
- ::GetIndString( outName, STRx_Menus, str_HideDrawing);
- else ::GetIndString( outName, STRx_Menus, str_ShowDrawing);
- outEnabled = true;
- break;
-
- case cmd_Copy:
- case cmd_ShowGrid:
- case cmd_SetSquareSize:
- case cmd_BlackAndWhite:
- outEnabled = mFullWindow;
- break;
-
- case cmd_ShowEdges:
- case cmd_ShowNodes:
- outEnabled = mFullWindow && mGraph;
- break;
-
- case cmd_BrightenGrid:
- outEnabled = mFullWindow && mShowGrid && mUseColor;
- break;
-
- case cmd_IncreaseSquareSize:
- outEnabled = mFullWindow && (mGridSquareSize < mMaxSquareSize);
- break;
-
- case cmd_DecreaseSquareSize:
- outEnabled = mFullWindow && (mGridSquareSize > 5);
- break;
-
- default:
- LCommander::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
- break;
- }
- }
-
- // ---------------------------------------------------------------------------
- // • SetGraph
- //
- // Called by: CGraphGAApp::InitForNoGraph
- // CGraphGAApp::ObeyCommand
- // CGraphGADoc::PrepareToIterate
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::SetGraph( CGraphPtr inGraph )
- {
- Int16 theGridSize;
-
- mGraph = inGraph;
- theGridSize = mApp -> GetGridSize();
- mMaxSquareSize = kMaxSquareSizes[ theGridSize ];
-
- if ( mGridSquareSize > mMaxSquareSize ) {
- mGridSquareSize = mMaxSquareSize;
- mNodeSize = SelectNodeSize();
- }
-
- InvalidateDrawing( false );
- }
-
- // ---------------------------------------------------------------------------
- // • InvalidateDrawing
- //
- // Called by: CGraphGADoc::PrepareToIterate
- // CGraphGADoc::SpendTime
- // CGraphPane::ObeyCommand
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::InvalidateDrawing( Boolean inDrawNow)
- {
- mDrawingIsOld = true;
- if ( inDrawNow )
- DrawTheBest();
- }
-
- // ---------------------------------------------------------------------------
- // • PlaceInClipboard (PRIVATE)
- //
- // Based on CDDItem.cp::PlaceInClipboard
- // by Gilles Dignard (gdignard@hookup.net)
- //
- // Called by: CGraphPane::ObeyCommand
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::PlaceInClipboard()
- {
- // Find the application's clipboard
-
- LClipboard* theClipboard = LClipboard::GetClipboard();
- SignalIf_( theClipboard == nil );
-
- // Add the picture of the object to the clipboard. The last parameter in
- // the SetData method indicates that we want the clipboard cleared before
- // the data we're passing in is added to the clipboard.
-
- PicHandle thePicH = CreatePict();
- theClipboard -> SetData('PICT', (Handle) thePicH, true);
- ::KillPicture(thePicH);
- }
-
- // ---------------------------------------------------------------------------
- // • CreatePict (PRIVATE)
- //
- // Create a handle to a pict containing the drawing.
- //
- // The calling procedure is responsible for issuing the
- // KillPicture(PicHandle) needed to clean up after we're done with it.
- //
- // Based on CDDItem.cp::CreatePict
- // by Gilles Dignard (gdignard@hookup.net)
- //
- // Called by: CGraphPane::PlaceInClipboard
- // ---------------------------------------------------------------------------
-
- PicHandle
- CGraphPane::CreatePict()
- {
- RgnHandle theCurrentClipRgn = ::NewRgn();
- ::GetClip( theCurrentClipRgn ); // Save the current clip region
-
- OpenCPicParams theOpenParams = { { mGridRect.top,
- mGridRect.left,
- mGridRect.bottom,
- mGridRect.right, },
- _72dpi, _72dpi, -2, 0, 0 };
-
- PicHandle thePicH = ::OpenCPicture( &theOpenParams );
-
- ::ClipRect( &mGridRect );
-
- EraseBackground( mGridRect, false );
-
- if ( mShowGrid ) //
- DrawGrid(); // Draw the graph !!
- if ( mGraph ) { //
- if ( mShowEdges ) //
- DrawEdges( true ); //
- if ( mShowNodes ) //
- DrawNodes(); //
- } //
-
- ::ClosePicture();
-
- ::SetClip( theCurrentClipRgn ); // Restore the clip region
-
- return thePicH;
- }
-
- // ---------------------------------------------------------------------------
- // • DrawSelf (PROTECTED)
- //
- // Called by: LView::Draw
- // ---------------------------------------------------------------------------
- // Slam the graph drawing from the offscreen to the 'real' screen...
-
- void
- CGraphPane::DrawSelf()
- {
- // If the graph has changed and we still haven't drawn it to
- // the offscreen, we better do it now, unless the drawing is
- // not shown at all...
-
- if ( mDrawingIsOld && mFullWindow ) {
- DrawTheBest();
- FocusDraw();
- }
-
- StColorPenState::Normalize();
-
- if ( mGWorld )
- mGWorld -> CopyImage( GetMacPort(), mFrameRect );
- }
-
- // ---------------------------------------------------------------------------
- // • DrawTheBest (PRIVATE)
- //
- // Called by: CGraphPane::InvalidateDrawing
- // CGraphPane::DrawSelf
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::DrawTheBest()
- {
- Rect theFrame = mFrameRect;
-
- // Draw only, if the drawing is visible...
-
- if ( mFullWindow && mGWorld ) {
-
- FocusDraw();
- StColorPenState theState;
-
- mGWorld -> BeginDrawing(); // Lets draw the graph...
-
- ::InsetRect( &theFrame, 1, 1 ); // A nice white frame...
-
- CalculateGridRect();
-
- EraseBackground( theFrame, true ); // Black or white background
-
- if ( mShowGrid ) //
- DrawGrid(); // Draw the graph !!
- if ( mGraph ) { //
- if ( mShowEdges ) //
- DrawEdges(); //
- if ( mShowNodes ) //
- DrawNodes(); //
- } //
-
- mGWorld -> EndDrawing(); // We are done with drawing...
-
- Rect pRect = mGridRect;
- LocalToPortPoint( topLeft( pRect ) );
- LocalToPortPoint( botRight( pRect ) );
- InvalPortRect( &pRect ); // Force update
-
- // We just drew the picture so its not old anymore!
-
- mDrawingIsOld = false;
- }
- }
-
- // ---------------------------------------------------------------------------
- // • EraseBackground (PRIVATE)
- //
- // Called by: CGraphPane::CreatePict
- // CGraphPane::DrawTheBest
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::EraseBackground( Rect &inEraseRect, Boolean inForceErase )
- {
- StColorPenState::Normalize();
-
- if ( mUseColor ) { // Set back color
- ::RGBBackColor( &blackRGB );
- // Else back color is white
- ::EraseRect( &inEraseRect );
- }
- else if ( mShowGrid || inForceErase )
- ::EraseRect( &inEraseRect );
- }
-
- // ---------------------------------------------------------------------------
- // • CalculateGridRect (PRIVATE)
- //
- // Called by: CGraphPane::ObeyCommand
- // CGraphPane::DrawTheBest
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::CalculateGridRect( )
- {
- mGridRect = mFrameRect;
- ::InsetRect( &mGridRect, 1, 1 );
-
- Int16 theGridWidth = (mApp -> GetGridSize()) * mGridSquareSize + 2;
-
- Int16 theInset = (mGridRect.right - mGridRect.left + 1
- - theGridWidth) / 2;
-
- ::InsetRect( &mGridRect, theInset, theInset);
-
- if ( theGridWidth % 2 ) {
- ++mGridRect.right;
- ++mGridRect.bottom;
- }
- }
-
- // ---------------------------------------------------------------------------
- // • DrawGrid (PRIVATE)
- //
- // Called by: CGraphPane::CreatePict
- // CGraphPane::DrawTheBest
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::DrawGrid()
- {
- const RGBColor frameRGB = { 0x1F74, 0xFFFF, 0x088A };
- const RGBColor dark_gridRGB = { 0x04A7, 0x1D10, 0x02AC };
- const RGBColor bright_gridRGB = { 0x0A05, 0x3E90, 0x05C1 };
-
- Rect theInnerFrame = mGridRect;
-
- ::InsetRect( &theInnerFrame, 1, 1);
-
- // Draw first the box...
-
- if ( mUseColor )
- ::RGBForeColor( &frameRGB );
- else ::RGBForeColor( &d_greyRGB );
-
- ::PenNormal();
- ::FrameRect( &mGridRect );
-
- if ( mUseColor ) {
- if (mDarkGrid)
- ::RGBForeColor( &dark_gridRGB );
- else ::RGBForeColor( &bright_gridRGB );
- }
- else ::RGBForeColor( &l_greyRGB );
-
- ::FrameRect( &theInnerFrame); // And this is the one inside mGridRect
-
- // ...and then the grid...
-
- Int16 theLeft = mGridRect.left,
- theTop = mGridRect.top,
- theRight = mGridRect.right,
- theBottom = mGridRect.bottom,
- theGridSize = mApp -> GetGridSize(),
- theX, theY,
- theDex;
-
- ::PenSize( 2,2 );
-
- for ( theDex = 1; theDex < theGridSize; ++theDex ) {
-
- theX = theY = theLeft + (theDex * mGridSquareSize);
-
- LineFromTo ( theX, // xFrom
- theTop + 1, // yFrom
- theX, // xTo
- theBottom - 3); // yTo
-
- LineFromTo ( theLeft + 1, // xFrom
- theY, // yFrom
- theRight - 3, // xTo
- theY); // yTo
- }
- }
-
- // ---------------------------------------------------------------------------
- // • DrawEdges (PRIVATE)
- //
- // Called by: CGraphPane::CreatePict
- // CGraphPane::DrawTheBest
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::DrawEdges( Boolean inDrawToPict )
- {
- Int16 theOneOneXY = mGridRect.left + (mGridSquareSize / 2) + 1;
-
- ::PenNormal();
-
- if ( mUseColor ) // Set edge color
- ::RGBForeColor( &goldenRGB );
- else
- if ( inDrawToPict )
- ::RGBForeColor( &blackRGB ); // black to pict
- else ::RGBForeColor( &D_greyRGB ); // very dark grey on screen
-
- mGraph -> DrawEdges( theOneOneXY, mGridSquareSize );
- }
-
- // ---------------------------------------------------------------------------
- // • DrawNodes (PRIVATE)
- //
- // Called by: CGraphPane::CreatePict
- // CGraphPane::DrawTheBest
- // ---------------------------------------------------------------------------
-
- void
- CGraphPane::DrawNodes()
- {
- const RGBColor nodeRGB = { 0xBDBD, 0x0000, 0x0000 }; // = Red
-
- Rect theOneOneRect;
-
- // We first set the rect to the upper left corner of
- // the (1,1) square. The size is set according to mNodeSize.
-
- ::SetRect( &theOneOneRect,
- mGridRect.left + 1, // Left
- mGridRect.top + 1, // Top
- mGridRect.left + 1 + mNodeSize, // Right
- mGridRect.top + 1 + mNodeSize); // Bottom
-
- // We then shift the rect to the middle of the square...
-
- Int16 theOffset = (mGridSquareSize - mNodeSize) / 2;
-
- ::OffsetRect( &theOneOneRect, theOffset, theOffset);
-
- if ( mUseColor ) // Set node color
- ::RGBForeColor( &nodeRGB );
- else ::RGBForeColor( &blackRGB );
-
- ::PenNormal();
-
- mGraph -> DrawNodes( theOneOneRect, mGridSquareSize);
- }
-
- // ---------------------------------------------------------------------------
- // • SelectNodeSize (PRIVATE)
- //
- // Called by: CGraphPane::ObeyCommand
- // CGraphPane::SetGraph
- // ---------------------------------------------------------------------------
-
- Int16
- CGraphPane::SelectNodeSize()
- {
- if ( mGridSquareSize < 10 ) return mGridSquareSize - 2;
- if ( mGridSquareSize < 14 ) return mGridSquareSize - 4;
- if ( mGridSquareSize < 17 ) return mGridSquareSize - 6;
- if ( mGridSquareSize < 21 ) return mGridSquareSize - 8;
- if ( mGridSquareSize < 24 ) return 11;
- if ( mGridSquareSize < 29 ) return 12;
- if ( mGridSquareSize < 31 ) return 13;
- if ( mGridSquareSize < 38 ) return 15;
-
- switch ( mGridSquareSize ) {
-
- case 38: return 18; break;
- case 42: return 20; break;
- case 49: return 25; break;
- case 57: return 27; break;
- case 67: return 31; break;
- case 85: return 41; break;
- case 113: return 55; break;
- case 173: return 85; break;
-
- default: return 0; // Should never happen...
- }
- }
-
- // ---------------------------------------------------------------------------
- // • GetNextSquareSize (PRIVATE)
- //
- // Called by: CGraphPane::ObeyCommand
- // ---------------------------------------------------------------------------
-
- Int16
- CGraphPane::GetNextSquareSize( Boolean inBigger )
- {
- Int16 *theScanner = kSquareSizes;
-
- while ( *theScanner != mGridSquareSize )
- theScanner++;
-
- if ( inBigger )
- theScanner++;
- else theScanner--;
-
- return *theScanner;
- }
-
- // ---------------------------------------------------------------------------
- // • ValidSquareSize (PRIVATE)
- //
- // Called by: CGraphPane::ObeyCommand
- // ---------------------------------------------------------------------------
-
- Boolean
- CGraphPane::ValidSquareSize( Int16 inSize )
- {
- Int16 *theScanner = kSquareSizes;
-
- if ( inSize < 5 || inSize > mMaxSquareSize )
- return false;
- else {
-
- while ( *theScanner < inSize )
- theScanner++;
-
- return (*theScanner == inSize);
- }
- }
-